#include <gtest/gtest.h>
#include "viml/parser.h"
#include "viml/ast.h"

namespace viml {

class ParserTest : public ::testing::Test {
protected:
    void SetUp() override {}
    void TearDown() override {}
};

TEST_F(ParserTest, ParseNumberLiteral) {
    std::string source = "42";
    Parser parser(source);
    
    auto expr = parser.parse_expression();
    
    ASSERT_TRUE(expr != nullptr);
    auto* number = dynamic_cast<NumberLiteral*>(expr.get());
    ASSERT_TRUE(number != nullptr);
    EXPECT_DOUBLE_EQ(number->value, 42.0);
}

TEST_F(ParserTest, ParseStringLiteral) {
    std::string source = "\"Hello, World!\"";
    Parser parser(source);
    
    auto expr = parser.parse_expression();
    
    ASSERT_TRUE(expr != nullptr);
    auto* string_lit = dynamic_cast<StringLiteral*>(expr.get());
    ASSERT_TRUE(string_lit != nullptr);
    EXPECT_EQ(string_lit->value, "Hello, World!");
}

TEST_F(ParserTest, ParseBinaryExpression) {
    std::string source = "1 + 2 * 3";
    Parser parser(source);
    
    auto expr = parser.parse_expression();
    
    ASSERT_TRUE(expr != nullptr);
    auto* binary = dynamic_cast<BinaryExpression*>(expr.get());
    ASSERT_TRUE(binary != nullptr);
    EXPECT_EQ(binary->op, BinaryExpression::Operator::ADD);
    
    // 左操作数应该是数字1
    auto* left = dynamic_cast<NumberLiteral*>(binary->left.get());
    ASSERT_TRUE(left != nullptr);
    EXPECT_DOUBLE_EQ(left->value, 1.0);
    
    // 右操作数应该是乘法表达式2*3
    auto* right = dynamic_cast<BinaryExpression*>(binary->right.get());
    ASSERT_TRUE(right != nullptr);
    EXPECT_EQ(right->op, BinaryExpression::Operator::MUL);
}

TEST_F(ParserTest, ParseLetStatement) {
    std::string source = "let x = 42";
    Parser parser(source);
    
    auto program = parser.parse();
    
    ASSERT_TRUE(program != nullptr);
    ASSERT_EQ(program->statements.size(), 1);
    
    auto* let_stmt = dynamic_cast<LetStatement*>(program->statements[0].get());
    ASSERT_TRUE(let_stmt != nullptr);
    EXPECT_EQ(let_stmt->name, "x");
    
    auto* value = dynamic_cast<NumberLiteral*>(let_stmt->value.get());
    ASSERT_TRUE(value != nullptr);
    EXPECT_DOUBLE_EQ(value->value, 42.0);
}

TEST_F(ParserTest, ParseEchoStatement) {
    std::string source = "echo \"Hello\"";
    Parser parser(source);
    
    auto program = parser.parse();
    
    ASSERT_TRUE(program != nullptr);
    ASSERT_EQ(program->statements.size(), 1);
    
    auto* echo_stmt = dynamic_cast<EchoStatement*>(program->statements[0].get());
    ASSERT_TRUE(echo_stmt != nullptr);
    
    auto* string_lit = dynamic_cast<StringLiteral*>(echo_stmt->expression.get());
    ASSERT_TRUE(string_lit != nullptr);
    EXPECT_EQ(string_lit->value, "Hello");
}

TEST_F(ParserTest, ParseMultipleStatements) {
    std::string source = "let x = 42\necho x";
    Parser parser(source);
    
    auto program = parser.parse();
    
    ASSERT_TRUE(program != nullptr);
    EXPECT_EQ(program->statements.size(), 2);
    
    // 第一个语句应该是let
    auto* let_stmt = dynamic_cast<LetStatement*>(program->statements[0].get());
    ASSERT_TRUE(let_stmt != nullptr);
    EXPECT_EQ(let_stmt->name, "x");
    
    // 第二个语句应该是echo
    auto* echo_stmt = dynamic_cast<EchoStatement*>(program->statements[1].get());
    ASSERT_TRUE(echo_stmt != nullptr);
}

TEST_F(ParserTest, ParseComplexExpression) {
    std::string source = "(1 + 2) * (3 - 4)";
    Parser parser(source);
    
    auto expr = parser.parse_expression();
    
    ASSERT_TRUE(expr != nullptr);
    auto* binary = dynamic_cast<BinaryExpression*>(expr.get());
    ASSERT_TRUE(binary != nullptr);
    EXPECT_EQ(binary->op, BinaryExpression::Operator::MUL);
    
    // 检查左操作数 (1 + 2)
    auto* left = dynamic_cast<BinaryExpression*>(binary->left.get());
    ASSERT_TRUE(left != nullptr);
    EXPECT_EQ(left->op, BinaryExpression::Operator::ADD);
    
    // 检查右操作数 (3 - 4)
    auto* right = dynamic_cast<BinaryExpression*>(binary->right.get());
    ASSERT_TRUE(right != nullptr);
    EXPECT_EQ(right->op, BinaryExpression::Operator::SUB);
}

} // namespace viml